package org.example;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Scanner;

public class ATMSystem {
        private static Account currentAccount = null;// 当前登录账户
        private static final Scanner scanner = new Scanner(System.in);// 输入扫描器

        public static void main(String[] args) {
            try (Connection connection = DatabaseUtil.getConnection()) {// 获取数据库连接
                LoggerUtil.logOperation(null, "ATM系统启动");// 记录系统启动日志

                AccountService accountService = new AccountService(connection);// 创建账户服务
                TransactionService transactionService = new TransactionService(connection, accountService);// 创建交易服务

                runMainLoop(accountService, transactionService);// 运行主循环
            } catch (SQLException e) {
                // 捕获数据库连接异常
                System.err.println("系统错误: " + e.getMessage());
                LoggerUtil.logError("系统运行异常", e);
            } finally {
                LoggerUtil.logOperation(null, "ATM系统关闭");
                scanner.close(); // 关闭扫描器
            }
        }
        /*
     * 主循环方法
     * @param accountService 账户服务
     * @param transactionService 交易服务
     */
    private static void runMainLoop(AccountService accountService, TransactionService transactionService) {// 运行主循环
        System.out.println("欢迎使用ATM系统！");
        while (true) {// 无限循环，直到用户选择退出
            if (currentAccount == null) {// 如果当前没有登录账户
                showLoginMenu(accountService);// 显示登录菜单
            } else {
                showATMMenu(accountService, transactionService);// 显示ATM菜单
            }
        }
    }

    /**
     * 显示登录菜单
     * @param accountService 账户服务
     */
    private static void showLoginMenu(AccountService accountService) {// 显示登录菜单
        System.out.println("\n=== ATM 登录界面 ===");
        System.out.println("1. 登录账户");
        System.out.println("2. 退出系统");

        int choice = getIntInput("请输入要操作的序号: ", 1, 2);// 获取用户输入的序号

        switch (choice) {// 根据用户选择执行相应操作
            case 1:
                login(accountService);// 登录账户
                break;
            case 2:
                System.out.println("感谢使用，再见！");// 退出系统
                System.exit(0);
        }
    }

    /**
     * 登录功能
     * @param accountService 账户服务
     */
    private static void login(AccountService accountService) {// 登录功能
        try {
            System.out.print("请输入账户号: ");// 提示用户输入账户号
            String accountId = scanner.nextLine();// 获取用户输入的账户号

            System.out.print("请输入密码: ");// 提示用户输入密码
            String password = scanner.nextLine();// 获取用户输入的密码

            currentAccount = accountService.login(accountId, password);// 调用账户服务的登录方法
            if (currentAccount != null) {// 如果登录成功
                System.out.println("登录成功！");
                System.out.println("欢迎，" + currentAccount.getName());// 显示欢迎信息
            } else {// 如果登录失败
                System.out.println("账户号或密码错误！");// 显示错误信息
            }
        } catch (SQLException e) {
            System.err.println("登录时发生数据库错误: " + e.getMessage());// 捕获数据库异常
            LoggerUtil.logError("登录数据库操作异常", e);
        }
    }

    /**
     * 显示ATM功能菜单
     * @param accountService 账户服务
     * @param transactionService 交易服务
     */
    private static void showATMMenu(AccountService accountService, TransactionService transactionService) {// 显示ATM功能菜单
        System.out.println("\n=== ATM 系统 ===");
        System.out.println("1. 存款");
        System.out.println("2. 取款");
        System.out.println("3. 转账");
        System.out.println("4. 查询余额");
        System.out.println("5. 交易记录");
        System.out.println("6. 修改密码");
        System.out.println("7. 退出登录");

        int choice = getIntInput("请输入要操作的序号: ", 1, 7);

        try {
            switch (choice) {
                case 1:
                    deposit(accountService, transactionService);// 存款功能
                    break;
                case 2:
                    withdraw(accountService, transactionService);// 取款功能
                    break;
                case 3:
                    transfer(accountService, transactionService);// 转账功能
                    break;
                case 4:
                    checkBalance(accountService);// 查询余额功能
                    break;
                case 5:
                    showTransactionHistory(transactionService);// 显示交易记录功能
                    break;
                case 6:
                    changePassword(accountService);// 修改密码功能
                    break;
                case 7:
                    logout();// 退出登录功能
                    break;
            }
        } catch (SQLException e) {
            System.err.println("操作时发生数据库错误: " + e.getMessage());// 捕获数据库异常
            LoggerUtil.logError("ATM操作数据库异常", e);
        }
    }

    /**
     * 存款功能
     * @param accountService 账户服务
     * @param transactionService 交易服务
     * @throws SQLException 数据库异常
     */
    private static void deposit(AccountService accountService, TransactionService transactionService) throws SQLException {// 存款功能
        double amount = getPositiveDoubleInput("请输入存款金额: ");// 获取存款金额

        accountService.deposit(currentAccount.getAccountId(), amount);// 调用账户服务的存款方法
        double newBalance = accountService.getAccountBalance(currentAccount.getAccountId());// 获取新的余额
        transactionService.recordTransaction(// 记录交易
                currentAccount.getAccountId(),// 账户号
                "DEPOSIT",// 交易类型
                amount,// 金额
                null,// 目标账户号
                newBalance// 新余额
        );
        currentAccount.setBalance(newBalance);// 更新当前账户的余额
        System.out.printf("存款成功！当前余额: %.2f元\n", newBalance);// 显示存款成功信息
    }

    /**
     * 取款功能
     * @param accountService 账户服务
     * @param transactionService 交易服务
     * @throws SQLException 数据库异常
     */
    private static void withdraw(AccountService accountService, TransactionService transactionService) throws SQLException {// 取款功能
        double amount = getPositiveDoubleInput("请输入取款金额: ");// 获取取款金额
        if (amount > currentAccount.getBalance()) {// 如果取款金额大于余额
            System.out.println("余额不足！");// 显示余额不足信息
            return;// 返回
        }
        accountService.withdraw(currentAccount.getAccountId(), amount);// 调用账户服务的取款方法
        double newBalance = accountService.getAccountBalance(currentAccount.getAccountId());// 获取新的余额

        transactionService.recordTransaction(// 记录交易
                currentAccount.getAccountId(),// 账户号
                "WITHDRAW",// 交易类型
                amount,// 金额
                null,// 目标账户号
                newBalance// 新余额
        );
        currentAccount.setBalance(newBalance);// 更新当前账户的余额
        System.out.printf("取款成功！当前余额: %.2f元\n", newBalance);// 显示取款成功信息
    }

    /**
     * 转账功能
     * @param accountService 账户服务
     * @param transactionService 交易服务
     * @throws SQLException 数据库异常
     */
    private static void transfer(AccountService accountService, TransactionService transactionService) throws SQLException {// 转账功能
        System.out.print("请输入目标账户号: ");// 获取目标账户号
        String targetAccountId = scanner.nextLine();// 获取用户输入的目标账户号
        if (!accountService.accountExists(targetAccountId)) {// 如果目标账户不存在
            System.out.println("目标账户不存在！");// 显示目标账户不存在信息
            return;// 返回
        }
        double amount = getPositiveDoubleInput("请输入转账金额: ");// 获取转账金额
        if (amount > currentAccount.getBalance()) {// 如果转账金额大于余额
            System.out.println("余额不足！");// 显示余额不足信息
            return;// 返回
        }
        try {// 尝试转账
            accountService.transfer(// 调用账户服务的转账方法
                    currentAccount.getAccountId(),// 源账户号
                    targetAccountId,// 目标账户号
                    amount,// 金额
                    transactionService// 交易服务
            );
            double fromBalanceAfter = accountService.getAccountBalance(currentAccount.getAccountId());// 获取源账户的新余额
            currentAccount.setBalance(fromBalanceAfter);// 更新当前账户的余额
            System.out.printf("转账成功！当前余额: %.2f元\n", fromBalanceAfter);// 显示转账成功信息
        } catch (SQLException e) {// 捕获数据库异常
            System.err.println("转账失败: " + e.getMessage());//显示转账失败信息
            LoggerUtil.logError("转账操作异常", e);// 记录异常日志
        }
    }
    /**
     * 查询余额
     * @param accountService 账户服务
     * @throws SQLException 数据库异常
     */
    private static void checkBalance(AccountService accountService) throws SQLException {// 查询余额功能
        double balance = accountService.getAccountBalance(currentAccount.getAccountId());// 获取账户余额
        System.out.printf("当前余额: %.2f元\n", balance);// 显示余额信息
    }

    /**
     * 显示交易记录
     * @param transactionService 交易服务
     */
    private static void showTransactionHistory(TransactionService transactionService) {// 显示交易记录功能
        try {// 尝试查询交易记录
            System.out.println("\n=== 交易记录 ===");// 显示交易记录标题
            List<Transaction> transactions = transactionService.getTransactions(currentAccount.getAccountId());// 获取交易记录列表

            if (transactions.isEmpty()) {// 如果交易记录列表为空
                System.out.println("暂无交易记录");// 显示暂无交易记录信息
            } else {// 如果交易记录列表不为空
                for (Transaction t : transactions) {// 遍历交易记录列表
                    System.out.println(t);// 显示交易记录信息
                }
            }
            System.out.println("\n按回车键返回");// 提示用户按回车键返回
            scanner.nextLine();
        } catch (SQLException e) {// 捕获数据库异常
            System.err.println("查询交易记录失败: " + e.getMessage());// 显示查询交易记录失败信息
            LoggerUtil.logError("查询交易记录数据库异常", e);// 记录异常日志
        }
    }
    /**
     * 修改密码
     * @param accountService 账户服务
     * @throws SQLException 数据库异常
     */
    private static void changePassword(AccountService accountService) throws SQLException {// 修改密码功能
        String oldPassword = getStringInput("请输入旧密码: ");// 获取旧密码
        String newPassword = getStringInput("请输入新密码: ");// 获取新密码
        if (accountService.changePassword(// 调用账户服务的修改密码方法
                currentAccount.getAccountId(),// 账户号
                oldPassword,// 旧密码
                newPassword// 新密码
        )) {
            System.out.println("密码修改成功！");// 显示密码修改成功信息
        } else {
            System.out.println("旧密码错误，修改失败！");// 显示旧密码错误信息
        }
    }

    /**
     * 退出登录
     */
    private static void logout() {// 退出登录功能
        String accountId = currentAccount.getAccountId();// 获取当前账户号
        currentAccount = null;// 清空当前账户
        System.out.println("已退出登录！");// 显示退出登录信息
        LoggerUtil.logOperation(accountId, "退出登录");// 记录退出登录日志
    }
    /**
     * 获取整数输入（带范围验证）
     */
    private static int getIntInput(String prompt, int min, int max) {// 获取整数输入（带范围验证）
        while (true) {//循环获取输入直到输入有效
            try {//尝试解析输入为整数
                System.out.print(prompt);// 显示提示信息
                String input = scanner.nextLine();// 获取用户输入
                int value = Integer.parseInt(input);// 解析输入为整数
                if (value >= min && value <= max) {// 如果输入在范围内
                    return value;// 返回输入值
                } else {
                    System.out.printf("请输入%d-%d之间的数字！\n", min, max);// 显示输入范围错误信息
                }
            } catch (NumberFormatException e) {// 捕获输入不是整数异常
                System.out.println("输入无效，请重新输入！");// 显示输入无效信息
            }
        }
    }
    /**
     * 获取正数输入（double类型）
     */
    private static double getPositiveDoubleInput(String prompt) {// 获取正数输入（double类型）
        while (true) {// 循环获取输入直到输入有效
            try {// 尝试解析输入为double类型
                System.out.print(prompt);// 显示提示信息
                String input = scanner.nextLine();// 获取用户输入
                double value = Double.parseDouble(input);// 解析输入为double类型
                if (value > 0) {// 如果输入大于0
                    return value;// 返回输入值
                } else {
                    System.out.println("请输入正数！");// 显示输入范围错误信息
                }
            } catch (NumberFormatException e) {// 捕获输入不是double类型异常
                System.out.println("输入无效，请重新输入！");// 显示输入无效信息
            }
        }
    }

    /**
     * 获取字符串输入
     * @param prompt 提示信息
     * @return 用户输入的字符串
     */
    private static String getStringInput(String prompt) {// 获取字符串输入
        System.out.print(prompt);// 显示提示信息
        return scanner.nextLine();// 获取用户输入
    }
}